package com.guomao;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@WebServlet("/download")
public class FileDownloadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        // 1. 获取文件路径（示例路径，实际可从请求参数或数据库读取）
        Path filePath = Paths.get(getServletContext().getRealPath("/files/测试 123.txt"));

        // 2. 检查文件是否存在
        if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在");
            return;
        }

        // 3. 自动检测 MIME 类型
        String mimeType = Files.probeContentType(filePath);
        response.setContentType(mimeType != null ? mimeType : "application/octet-stream");

        // 4. RFC 5987 文件名编码（使用 URLEncoder，但替换 "+" 为 "%20"）
        String fileName = filePath.getFileName().toString();
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                .replace("+", "%20"); // 关键：RFC 5987 要求空格编码为 %20，而非 +

        response.setHeader("Content-Disposition",
                "attachment; filename*=UTF-8''" + encodedFileName);

        // 5. 设置文件长度
        response.setContentLengthLong(Files.size(filePath));

        // 6. 高效流传输（NIO Files.copy）
        try {
            Files.copy(filePath, response.getOutputStream());
        } catch (IOException e) {
            if (!response.isCommitted()) {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "下载失败");
            }
        }
    }
}